package com.mobilereports.service;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.mobilereports.model.Record;
import com.mobilereports.model.Report;
import com.mobilereports.model.ReportColumn;

public class ReportsServiceImpl extends ReportsService {
	private static final String PREFIX = "http://192.168.56.1:8080/reports-examples/app/";
	private static final String REPORTS_URL = PREFIX + "reports.htm";
	//private static final String REPORTS_URL = "http://wiadomosci.wp.pl/kat,1342,ver,rss,rss.xml";
	private static final String META_MODEL_URL = PREFIX + "reportMetaModel.htm";
	private static final String DATA_URL = PREFIX + "reportFetch.htm";
	
	@Override
	public List<Report> getReports() {
		List<Report> reports = new LinkedList<Report>();
		
		for(Record r: fetchRecords(REPORTS_URL)) {
			Report report = new Report();
			report.setId(r.getAttributeAsString("id"));
			report.setName(r.getAttributeAsString("Name"));
			reports.add(report);
		}
		
		return reports;
	}

	@Override
	public List<ReportColumn> getReportColumns(Report report) {
		List<ReportColumn> columns = new LinkedList<ReportColumn>();
		
		for(Record r: fetchRecords(META_MODEL_URL + "?reportId=" + report.getId())) {
			ReportColumn column = new ReportColumn();
			column.setTitle(r.getAttributeAsString("title"));
			column.setName(r.getAttributeAsString("name"));
			String category = r.getAttributeAsString("category");
			if(category.equals("MEASURE")) {
				column.setMeasure(true);
			}
			else if(category.equals("CANDITATE")) {
				column.setHierarchyCandidate(true);
			}
			columns.add(column);
		}
		
		return columns;
	}

	@Override
	public List<Record> fetchData(Report report, List<ReportColumn> hierarchy,
			String path) {
		String url = DATA_URL;
		url += "?reportId=" + report.getId();
		String h = "";
		boolean first = true;
		for(ReportColumn c: hierarchy) {
			if(first) {
				first = false;
			}
			else {
				h += ";";
			}
			h += c.getName();
		}
		url += "&hierarchy=" + h;
		url += "&parentPath=" + path;
		
		return fetchRecords(url);
	}

	private List<Record> fetchRecords(String urlString) {
		List<Record> records = new LinkedList<Record>();
		
		try {
			Document doc = getXMLDocument(urlString);
			
			NodeList nodeList = doc.getElementsByTagName(Record.RECORD_ELEMENT);
			for(int i=0;i<nodeList.getLength();++i) {
				Element e = (Element)nodeList.item(i);
				NodeList childList = e.getChildNodes();
				
				Record r = new Record();
				for(int j=0;j<childList.getLength();++j) {
					Node n = childList.item(j);
					if(n instanceof Element) {
						Element c = (Element)n;
						r.setAttribute(c.getNodeName(), c.getTextContent());
					}
				}
				
				records.add(r);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return records;
	}
	
	private Document getXMLDocument(String urlString) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = factory.newDocumentBuilder();
		
		Document doc = documentBuilder.parse(getInputStream(urlString));
		return doc;
	}
	
	private InputStream getInputStream(String urlString) throws IOException {
		URL url = new URL(urlString);
		
		/*
		System.out.println(url.getProtocol());
		System.out.println(url.getPort());
		System.out.println(url.getPath());
		System.out.println(url.getAuthority());
		System.out.println(url.getHost());
		System.out.println(url.getQuery());
		*/
		
		return url.openStream();
	}
	
	public static void main(String[] args) {
		ReportsServiceImpl service = new ReportsServiceImpl();
		
		for(Report r: service.getReports()) {
			System.out.println(r.getId() + " " + r.getName());
			System.out.println("COLUMNS:");
			List<ReportColumn> columns = service.getReportColumns(r);
			for(ReportColumn c: columns) {
				System.out.println("\t" + c.getName() + " " + c.getTitle() + " " + c.isHierarchyCandidate() + " " + c.isMeasure());
			}
			System.out.println("EXAMPLE DATA:");
			
			List<ReportColumn> hierarchy = new LinkedList<ReportColumn>();
			for(ReportColumn c: columns) {
				if(c.isHierarchyCandidate()) {
					hierarchy.add(c);
					break;
				}
			}
			
			for(Record record: service.fetchData(r, hierarchy, "null")) {
				
				System.out.print("\t");
				for(ReportColumn c: columns) {
					System.out.print(record.getAttributeAsString(c.getName()) + " ");
				}
				System.out.println();
			}
		}
		
	}
	
}